/*
Command_Colorspray.cs
Version 1.4
snicker7
Released: 03/08/06
Updated: 06/19/06
Version: RunUO 2.0
Description:
Creates a command for GameMasters and up for
an oldschool dnd type colorspray. Ability to
just do damage or always kill anyone in the
cone. Defaults to a 5 tile radius cone and
level of 10. (damage is (level)d10 100% energy =)
if you specify the level argument as '666'
all mobiles in the cone will be Kill()'d and
not damaged.

Also has a couple methods so you can add
colorspray to items and weapons if you want.
Usage:
[colorspray
[colorspray (cone radius)
[colorspray (cone radius) (level)
 */
using System;
using System.Collections;
using System.Collections.Generic;
using Server;

namespace Server.Commands
{
	public class ColorSpray
	{
		public static void Initialize()
		{
			CommandSystem.Register( "colorspray", AccessLevel.GameMaster, new CommandEventHandler( ColorSpray_OnCommand ) );
		}
		
		[Usage( "colorspray [cone distance(5)] [level(10)]" )]
		[Description( "Colorspray everything in the cone for (level)d10 energy damage, level 666 for always kill." )]
		public static void ColorSpray_OnCommand( CommandEventArgs e )
		{
			int dist = 5;
			int level = 10;
			if(e.Length>0)
				dist = e.GetInt32(0);
			if(e.Length>1)
				level = e.GetInt32(1);
			if(dist>12){dist=12;}
			ColorSprayInit(dist,level,e.Mobile,true);
		}
		
		//use this method for weapons in OnHit
		public static void ColorSprayInit(int dist, int level, Mobile attacker, Mobile victim, bool animate) {
			Direction dir = Utility.GetDirection(attacker.Location, victim.Location);
			ColorSprayInit(dist,level,attacker,victim.Location,dir,animate);
		}
		
		//use this method for basic things
		public static void ColorSprayInit(int dist, int level, Mobile mobile, bool animate) {
			ColorSprayInit(dist,level,mobile,mobile.Location,mobile.Direction,animate);
		}
		
		//core method
		public static void ColorSprayInit(int dist, int level, Mobile mobile, Point3D start, Direction direction, bool animate)
		{
			Point3DList path = new Point3DList();
			
			if(animate){
				mobile.PublicOverheadMessage( Network.MessageType.Spell, mobile.SpeechHue, true, "Vas Cul Ylem", false );
				mobile.Animate(212, 7, 1, true, false, 0);
			}
			
			for(int i=0;i<dist+1;i++){
				int x=0,y=0;
				switch((int)direction){
						case (int)Direction.Running:	case (int)Direction.North: { y-=i; break; }
						case 129:						case (int)Direction.Right: { y-=i;x+=i; break; }
						case 130:						case (int)Direction.East: { x+=i; break; }
						case 131:						case (int)Direction.Down: { x+=i;y+=i; break; }
						case 132:						case (int)Direction.South: { y+=i; break; }
						case 133:						case (int)Direction.Left: { y+=i;x-=i; break; }
						case 134:						case (int)Direction.West: { x-=i; break; }
						case (int)Direction.ValueMask:	case (int)Direction.Up: { x-=i;y-=i; break; }
				}
				path.Add(start.X+x,start.Y+y,start.Z);
			}
			new SprayTimer(mobile,path,direction,1,dist+2,level).Start();
		}
		
		private static void doSpray(Mobile sprayer, Point3DList path, Direction dir, int i, int level){
			if(path.Count>i){ //please to not crashing!
				Point3D point = path[i];
				int o = i-1;
				Server.Effects.PlaySound(point, sprayer.Map, 492);
				Server.Effects.PlaySound(point, sprayer.Map, 0x231);
				for(int rn=0;rn<(o*2)+1;rn++){
					int y=0,x=0,y2=0,x2=0;
					bool diag = false;
					switch((int)dir){
							case (int)Direction.Running:	case (int)Direction.North: { x=x-o+rn; break; }
							case 129:						case (int)Direction.Right: { x=x-o+rn;y=y-o+rn; break; }
							case 130:						case (int)Direction.East: { y=y-o+rn; break; }
							case 131:						case (int)Direction.Down: { y=y-o+rn;x=x+o-rn; break; }
							case 132:						case (int)Direction.South: { x=x+o-rn; break; }
							case 133:						case (int)Direction.Left: { x=x+o-rn;y=y+o-rn; break; }
							case 134:						case (int)Direction.West: { y=y+o-rn; break; }
							case (int)Direction.ValueMask:	case (int)Direction.Up: { y=y+o-rn;x=x-o+rn; break; }
					}
					switch((int)dir){
							case 129:						case (int)Direction.Right: { y2++;diag=true; break; }
							case 131:						case (int)Direction.Down: { x2--;diag=true; break; }
							case 133:						case (int)Direction.Left: { y2--;diag=true; break; }
							case (int)Direction.ValueMask:	case (int)Direction.Up: { x2++;diag=true; break; }
							default: {break;}
					}
					Point3D ep = new Point3D(point.X+x,point.Y+y,point.Z);
					Point3D ep2 = new Point3D(ep.X+x2,ep.Y+y2,ep.Z);
					if(diag&&i>=((2*path.Count)/3))
						return;
					if(diag&&rn<(o*2))
						Effects.SendLocationEffect(ep2, sprayer.Map, 0x374A, 15, RandomHue(), 0);
					Effects.SendLocationEffect(ep, sprayer.Map, 0x374A, 15, RandomHue(), 0);
					List<Mobile> die = new List<Mobile>();
					foreach(Mobile sprayed in sprayer.Map.GetMobilesInRange(ep,0)){
						if(sprayed != sprayer)
							die.Add(sprayed);
					}
					foreach(Mobile sprayed in sprayer.Map.GetMobilesInRange(ep2,0)){
						if(sprayed != sprayer)
							die.Add(sprayed);
					}
					for(int k=0;k<die.Count;k++){
						Mobile died = die[k];
						if(!died.Deleted&&died!=null){
							if(level==666){
								died.Kill();
							}
							else{
								AOS.Damage(died,sprayer,Utility.RandomMinMax(level,level*10),0,0,0,0,100);
							}
						}
					}
				}
			}
		}
		
		private static int RandomHue() {
			switch (Utility.Random(5)) {
				default:
					case 0: return Utility.RandomBlueHue();
					case 1: return Utility.RandomGreenHue();
					case 2: return Utility.RandomRedHue();
					case 3: return Utility.RandomYellowHue();
					case 4: return Utility.RandomNeutralHue();
			}
		}
		
		private class SprayTimer : Timer
		{
			private Direction m_Dir;
			private int m_I,m_IMax,m_Level;
			private Point3DList m_Path;
			private Mobile m_Sprayer;

			public SprayTimer(Mobile sprayer, Point3DList path, Direction dir, int i, int imax, int level) : base(TimeSpan.FromTicks(2)) {
				m_Dir=dir;
				m_I=i;
				m_IMax=imax;
				m_Path=path;
				m_Sprayer=sprayer;
				m_Level=level;
				Priority = TimerPriority.FiftyMS;
			}

			protected override void OnTick() {
				doSpray(m_Sprayer,m_Path,m_Dir,m_I,m_Level);
				if(m_I<m_IMax)
					new SprayTimer(m_Sprayer,m_Path,m_Dir,m_I+1,m_IMax,m_Level).Start();
				Stop();
			}
		}
		
	}
}
